package com.scanner;

import com.annotation.Cmd;
import com.annotation.Module;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 使用beanPostProcessor 在bean初始化之后加载所有的bean
 * 接下来扫描bean对象下的方法中载有@Cmd， 注解的方法
 * 最后创建对应的Invoker，并把他们加入到InvokerTable中
 * @author 顾志杰
 * @date 2021/3/16-10:07
 */
@Component
public class NettyProcessBeanScanner implements BeanPostProcessor {
    /**
     * bean初始化之前
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }

    /**
     * bean初始化之后
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // 1. 首先获取当前bean的class类型
        Class<?> clazz = bean.getClass();
        // 2. isAnnotation 有没有注解
        //    isAnnotationPresent 有没有指定的注解
        boolean isPresent = clazz.isAnnotationPresent(Module.class);
        if(isPresent){
            Method[] methods = clazz.getMethods();
            if(methods.length > 0){
                for (Method m : methods) {
                    Module module = clazz.getAnnotation(Module.class);
                    Cmd cmd = m.getAnnotation(Cmd.class);
                    if(cmd == null){
                        continue;
                    }
                    String moduleValue = module.module();
                    String cmdValue = cmd.cmd();
                    // 只需要把moduleValue + cmdValue的值与对应的反射对象(invoker)管理起来(map)
                    if(InvokerTable.getInvoker(moduleValue,cmdValue) == null){
                        InvokerTable.addInvoker(moduleValue,cmdValue,Invoker.createInvoker(m,bean));
                    }else{
                        System.out.println("模块下的命令对应的程序缓存已经存在，module: " + moduleValue +" , cmd: "+cmdValue);
                    }

                }
            }
        }
        return null;
    }
}
